﻿using System.Reflection;
using ECommerce.Web.Models;
using ECommerce.Web.NHibernate.EventListeners;
using ECommerce.Web.NHibernate.Mappings.EntityMappings;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate.Cfg;
using NHibernate.Event;

namespace ECommerce.Web.NHibernate.ConfigurationBuilders
{
    public class DefaultConfigurationBuilder : IConfigurationBuilder
    {
        public Configuration Build(IPersistenceConfigurer persistenceConfigurer)
        {
            Assembly mappingAssembly = typeof(EntityMap<>).Assembly;

            Configuration configuration = Fluently
                .Configure()
                .Database(persistenceConfigurer)
                .Mappings(x =>
                    {
                        x.HbmMappings
                            .AddFromAssembly(mappingAssembly);
                        x.FluentMappings
                            .Conventions.AddAssembly(mappingAssembly)
                            .AddFromAssembly(mappingAssembly);
                        x.AutoMappings
                            .Add(GetAutoPersistenceModel());
                    })
                .BuildConfiguration();

            SetListeners(configuration);

            return configuration;
        }
      
        private AutoPersistenceModel GetAutoPersistenceModel()
        {
            var model = new AutoPersistenceModel();

            Assembly entityAssembly = typeof(Entity).Assembly;

            model.AddEntityAssembly(entityAssembly).Where(x => x.BaseType == typeof(Entity) && !x.IsAbstract);

            return model;
        }

        private void SetListeners(Configuration configuration)
        {
            var changeConflictListener = new ChangeConflictEventListener();
            var validationListener = new ValidationEventListener();

            configuration.SetListener(ListenerType.PreInsert, validationListener);

            configuration.SetListeners(ListenerType.PreUpdate, new IPreUpdateEventListener[]
                                                                   {
                                                                       changeConflictListener,
                                                                       validationListener
                                                                   });
        }  
    }
}
